package fr.inserm.u915.tabixserver;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import fr.inserm.u915.tabixserver.segparser.ParseException;
import fr.inserm.u915.tabixserver.segparser.SegmentParser;

@SuppressWarnings("serial")
public class TabixController extends HttpServlet
	{
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
	throws ServletException, IOException
		{
		final Model model=(Model)this.getServletContext().getAttribute(TabixCtxListener.TABIX_MODEL_ATTRIBUTE);
		if(model==null) throw new ServletException("model?");
				
		
		String pathInfo=req.getPathInfo();
		if(pathInfo!=null)
			{
			while(pathInfo.startsWith("/")) pathInfo=pathInfo.substring(1);
			while(pathInfo.endsWith("/")) pathInfo=pathInfo.substring(0,pathInfo.length()-1);
			}
		
		if(pathInfo==null || pathInfo.isEmpty())
			{
			req.getRequestDispatcher("/WEB-INF/jsp/main.jsp").forward(req, resp);
			return;
			}
		String pathItems[]=pathInfo.split("[/]+");
		String query= req.getParameter("q");
		String what=req.getParameter("what");
		
		
		if(pathItems[0].equals("build"))
			{
			//WSDL
			if(pathItems.length>1 && pathItems[1].endsWith(".wsdl"))
				{
				String buildName=pathItems[1];
				buildName=buildName.substring(0,buildName.lastIndexOf('.'));
				Build build=model.getBuildById(buildName);
				if(build==null) throw new ServletException(
						"unknown build id:"+buildName);
				req.setAttribute("build", build);
				req.getRequestDispatcher("/WEB-INF/wsdl").forward(req, resp);
				return;
				}
			//XSD
			if(pathItems.length>1 && pathItems[1].endsWith(".xsd"))
				{
				String buildName=pathItems[1];
				buildName=buildName.substring(0,buildName.lastIndexOf('.'));
				Build build=model.getBuildById(buildName);
				if(build==null) throw new ServletException(
						"unknown build id:"+buildName);
				req.setAttribute("build", build);
				req.getRequestDispatcher("/WEB-INF/xsd").forward(req, resp);
				return;
				}
			//XSLT
			if(pathItems.length>1 && (pathItems[1].endsWith(".xsl") || pathItems[1].endsWith(".xslt")) )
				{
				String buildName=pathItems[1];
				buildName=buildName.substring(0,buildName.lastIndexOf('.'));
				Build build=model.getBuildById(buildName);
				if(build==null) throw new ServletException(
						"unknown build id:"+buildName);
				req.setAttribute("build", build);
				req.setAttribute("tns", TNS.NS);
				req.getRequestDispatcher("/WEB-INF/jsp/xslt.jsp").forward(req, resp);
				return;
				}
			//SOAP
			String contentType=req.getContentType();
			if(contentType!=null &&
				pathItems.length>2 &&
				contentType.contains("text/xml") &&
				!pathItems[1].isEmpty() &&
				pathItems[2].equals("soap")
				)
				{
				String buildName=pathItems[1];
				Build build=model.getBuildById(buildName);
				if(build==null) throw new ServletException(
						"unknown build id:"+buildName);
				req.setAttribute("build", build);
				req.getRequestDispatcher("/WEB-INF/soap").forward(req, resp);
				return;
				}
			
			if(pathItems.length>1)
				{
				String buildName=pathItems[1];
				Build build=model.getBuildById(buildName);
				if(build==null) throw new ServletException(
						"unknown build id:"+buildName+"\npathinfo:"
						+req.getPathInfo()+"\nuri:"+
						req.getRequestURI()+
						"\nurl:"+req.getRequestURL()
						+"\n"+req.getPathTranslated()
						);
				req.setAttribute("build", build);
				req.setAttribute("instances",build.getAllInstances());
				
			
				List<Segment>  segs=null;
				if(query!=null)
					{
					try
						{
						segs=SegmentParser.parseMany(query);
						req.setAttribute("segments", segs);
						}
					catch(ParseException err)
						{
						throw new ServletException("Syntax Error in segments:"+query,err);
						}
					}
				
				if( "Sequence".equals(what) && segs!=null && !segs.isEmpty())
					{
					req.getRequestDispatcher("/WEB-INF/fasta").forward(req, resp);
					return;
					}
				else if( "Annotations".equals(what) && segs!=null && !segs.isEmpty())
					{
					req.getRequestDispatcher("/WEB-INF/annotation").forward(req, resp);
					return;
					}
				
				
				
				if(pathItems.length>2 && pathItems[2].equals("schema"))
					{
					OutputStream out=resp.getOutputStream();
					try
						{
						XMLOutputFactory xmlfactory= XMLOutputFactory.newInstance();
						XMLStreamWriter w= xmlfactory.createXMLStreamWriter(out,resp.getCharacterEncoding());
						w.writeStartDocument(resp.getCharacterEncoding(),"1.0");
						build.writeXsd(w);
						w.flush();
						w.close();
						}
					catch(XMLStreamException err)
						{
						throw new IOException(err);
						}
					finally
						{
						out.flush();
						out.close();
						}
					return;
					}
				
				
				req.getRequestDispatcher("/WEB-INF/jsp/build.jsp").forward(req, resp);
				return;
				}
			}
		
		resp.setContentType("text/plain");
		PrintWriter out=resp.getWriter();
		out.println("Hello world");
		out.println(req.getPathInfo());
		out.println(req.getContextPath());
		out.println(req.getRequestURI());
		out.println(req.getServletPath());
		out.flush();
		out.close();
		}
	
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doGet(req, resp);
		}
	}
